package com.raymond.cmpp.utils;

import cn.hutool.core.util.StrUtil;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * @author :  raymond
 * @version :  V1.0
 * @date :  2022-12-07 10:59
 */
public class SmsUtil {
    /**
     * 短信拆分后的信息
     * @param msg 短信内容包含签名
     * @param msgLen 拆分长度
     * @param signatureLen 签名长度
     * @param isLeadSignature 是否是前置签名
     * @param signType 是否是运营商添加签名, true是运营商添加签名
     * @param serialNum 长短信头序列号
     * @return 短信内容拆分后的信息
     */
    public static List<String> msgSplit(String msg, int msgLen, int signatureLen, boolean isLeadSignature, boolean signType, byte serialNum) {
        //当前短信最后一条长度
        int currentEndLen = msg.length() % msgLen;
        //获取总条数
        int msgNum = msg.length() % msgLen == 0 ? msg.length() / msgLen : msg.length() / msgLen + 1;
        //如果是后置签名最后一条短信多出签名的长度,如果为负数表示签名长度不够,需要将签名的长度补入到前面,并且要多一个长度
        int isSignature = 0;
        if(!isLeadSignature && currentEndLen > 0  && signType) {
            isSignature = currentEndLen - signatureLen - 1;
        }
        //TP_udhi
        byte[] tpUdhiHead = new byte[]{0x05, 0x00, 0x03, serialNum, (byte)msgNum, 0x01};
        List<String> msgList = new LinkedList<>();
        for (int i = 0; i < msgNum; i++) {
            tpUdhiHead[5] = (byte) (i + 1);
            //获取最后的长度
            int lastLen = i == msgNum - 1 ? msg.length() : (i + 1) * msgLen;
            //如果需要处理后置短信签名,在倒数第二条长度加少的长度位
            if (isSignature < 0 && i == msgNum - 2) {
                lastLen += isSignature;
            } else if (isSignature < 0 && i == msgNum - 1) {
                lastLen -= isSignature;
            }
            //合并两个字节
            byte[] bytes;
            if (signType && isLeadSignature && i == 0) {
                bytes = byteMerger(tpUdhiHead, msg.substring(signatureLen, lastLen).getBytes());
            } else if (signType && !isLeadSignature && i == msgNum - 1) {
                bytes = byteMerger(tpUdhiHead, msg.substring(i * msgLen + Math.min(isSignature, 0), lastLen - signatureLen + Math.min(isSignature, 0)).getBytes());
            } else {
                bytes = byteMerger(tpUdhiHead, msg.substring(i * msgLen, lastLen).getBytes());
            }
            msgList.add(new String(bytes));
        }
        return msgList;
    }

    static Set<Character> characterSet = new HashSet<>();
    static Set<Byte> byteSet = new HashSet<>();

    static {
        char[] cs = new char[]{'|', '^', '{', '}', '~', '[', ']', '\\'};
        for (char c : cs) {
            characterSet.add(c);
        }
        byte[] bytes = new byte[]{0X00, 0X01, 0X02, 0X03, 0X04, 0X05, 0X06, 0X07, 0X08, 0X09, 0X0B, 0X0C, 0X0D, 0X0E, 0X0F, 0X10,
                0X11, 0X12, 0X13, 0X14, 0X15, 0X16, 0X17, 0X18, 0X19, 0X1A, 0X1B, 0X1C, 0X1D, 0X1E, 0X1F, 0X7F};
        for (byte aByte : bytes) {
            byteSet.add(aByte);
        }

    }



    /**
     * 短信拆分后的信息
     * @param msg 短信内容包含签名
     * @param msgLen 拆分长度
     * @param signatureLen 签名长度
     * @param isLeadSignature 是否是前置签名
     * @param signType 是否是运营商添加签名, true是运营商添加签名
     * @return 短信内容拆分后的信息
     */
    public static List<String> msgSplitLongSms(String msg, int msgLen, int signatureLen, boolean isLeadSignature,
                                               boolean signType, byte serialNum) {
        List<String> singleSms = msgSplitLongSms(msg, msgLen);
        List<String> msgList = new LinkedList<>();
        byte[] tpUdhiHead = new byte[]{0x05, 0x00, 0x03, serialNum, (byte)singleSms.size(), 0x01};
        int size = singleSms.size();
        for (int i = 0; i < size; i++) {
            String singleSm = singleSms.get(i);
            tpUdhiHead[5] = (byte) (i + 1);
            if (signType) {
                //由运营商加签名并且是前签名处理
                if (isLeadSignature && i == 0) {
                    singleSm = singleSm.substring(signatureLen);
                }
                //由运营商加签名并且是后置签名,并且倒数第二条需要后移处理
                if (!isLeadSignature && i == (size - 2)) {
                    String s = singleSms.get(i + 1);
                    int i1 = signatureLen - s.length() + 1;
                    if (i1 > 0) {
                        s = singleSm.substring(singleSm.length() - i1, singleSm.length() - i1 + 1);
                        singleSm = singleSm.substring(0, singleSm.length() - i1);
                        msgList.add(new String(byteMerger(tpUdhiHead, singleSm.getBytes())));
                        tpUdhiHead[5] = (byte) (i + 2);
                        msgList.add(new String(byteMerger(tpUdhiHead, s.getBytes())));
                        break;
                    }
                }
                if (!isLeadSignature && i == (size - 1)) {
                    singleSm = singleSm.substring(0, singleSm.length() - signatureLen);
                }
            }
            byte[] bytes = byteMerger(tpUdhiHead, singleSm.getBytes());
            msgList.add(new String(bytes));
        }
        return msgList;
    }

    public static int getEnSmsSignLen(String msg) {
        if (StrUtil.isEmpty(msg)) {
            return 0;
        }
        char[] chars = msg.toCharArray();
        int len = 0;
        for (char aChar : chars) {
            if (aChar > 127) {
                return -1;
            }
            len++;
            if (characterSet.contains(aChar)) {
                len++;
            }
        }
        return len;
    }

    /**
     * 短信拆分后的信息
     * @param msg 短信内容包含签名
     * @param msgLen 拆分长度
     * @return 短信内容拆分后的信息
     */
    private static List<String> msgSplitLongSms(String msg, int msgLen) {
        List<String> msgList = new LinkedList<>();
        StringBuilder sb = new StringBuilder();
        int currentLen = 0;
        int index = 0;
        int maxLen = msg.length();
        while (index < maxLen) {
            currentLen ++;
            char c = msg.charAt(index);
            if (characterSet.contains(c)) {
                currentLen ++;
            }
            if (currentLen > msgLen) {
                msgList.add(sb.toString());
                sb.setLength(0);
                currentLen = 0;
                continue;
            }
            if (byteSet.contains((byte) c)) {
                sb.append(" ");
            } else {
                sb.append(c);
            }
            index ++;
        }
        if (sb.length() > 0) {
            msgList.add(sb.toString());
        }
        return msgList;
    }

    /**
     * 合并两个byte数组
     *
     * @param data1
     * @param data2
     * @return
     */
    public static byte[] byteMerger(byte[] data1, byte[] data2) {
        byte[] data3 = new byte[data1.length + data2.length];
        System.arraycopy(data1, 0, data3, 0, data1.length);
        System.arraycopy(data2, 0, data3, data1.length, data2.length);
        return data3;
    }
}
